<?php

namespace app\socket\controller;

use app\admin\model\ExchangeMarket;
use app\admin\model\Member;
use app\common\Jwt;
use app\common\Status;
use app\common\CacheKey;
use app\service\Redis;
use think\facade\Cache;
use think\facade\Lang;
use think\worker\Server;
use Workerman\Lib\Timer;

// 心跳间隔8秒
define('HEARTBEAT_TIME', 8);

class Worker extends Server
{
    protected $user = [];
    protected $token = '';
    protected $data = [];

    protected $socket = 'websocket://0.0.0.0:4431';


    /**
     * 收到信息
     * @param $connection
     * @param $data
     */
    public function onMessage($connection, $data)
    {
        $data = json_decode($data, true);
        $type = isset($data['type']) ? $data['type'] : '';
        // 心跳检测
        if ($type == 'heartbeat') {
            if (isset($data['param']['timestamp']) && (time() - $data['param']['timestamp']) <= 10) {
                $list = [
                    'type' => $type,
                    'code' => Status::SUCCESS,
                    'data' => [],
                    'msg' => '',
                ];
                $msg = $this->send_msg($list);
                $connection->lastMessageTime = time();
                $connection->send($msg);
            } else {
                $this->onClose($connection);
            }
        }
    }

    /**
     * 当连接建立时触发的回调函数
     * @param $connection
     */
    public function onConnect($connection)
    {
        $connection->onWebSocketConnect = function ($connection) {
            if (!isset($_GET['token'])) {
                $this->onError($connection, Status::NO_TOKEN, '请先登录');
                $connection->close();
            } else {
                $token = $_GET['token'];
                $this->checkToken($connection, $token);
            }
        };
        // 实时推送
        Timer::add(2, function () use ($connection) {
            $this->market($connection);
        });
    }

    /**
     * 当连接断开时触发的回调函数
     * @param $connection
     */
    public function onClose($connection)
    {
        // 关闭连接
        $connection->close();
        // 清除token
//        if (isset($this->token)) {
//            $redis = Redis(5);
//            $key = sprintf(CacheKey::CONNECT, $this->token);
//            $bind_key = sprintf(CacheKey::CLIENT_ID_UID, $connection->id);
//            $redis->del($key);
//            $redis->del($bind_key);
//        }
    }

    /**
     * 当客户端的连接上发生错误时触发
     * @param $connection
     * @param $code
     * @param $msg
     */
    public function onError($connection, $code, $msg)
    {
        $list = [
            'code' => $code,
            'msg' => $msg,
        ];
        $connection->send($this->send_msg($list));
    }

    /**
     * 每个进程启动
     * @param $worker
     */
    public function onWorkerStart($worker)
    {
//        Timer::add(2, function () use ($worker) {
//            $time_now = time();
//            $redis = Redis(5);
//            foreach ($worker->connections as $connection) {
//                $bind_key = sprintf(CacheKey::CLIENT_ID_UID, $connection->id);
//                // 检验Token是否过期
//                $uid = Cache::get($this->token);
//                if (!$uid) {
//                    $this->onClose($connection);
//                }
//                // 主动推送信息
//                $key = sprintf(CacheKey::AUTH_USER, $uid);
//                $status = Cache::get($key);
//                if ($status && $uid == $redis->get($bind_key)) {
//                    if ($status == 1) {
//                        $code = Status::SUCCESS;
//                    } else {
//                        $code = Status::FAILED;
//                    }
//                    $list = [
//                        'type' => 'AuthMessage',
//                        'code' => $code,
//                        'data' => [],
//                        'msg' => '',
//                    ];
//                    $msg = $this->send_msg($list);
//                    $connection->send($msg);
//                }
//                // 有可能该connection还没收到过消息，则lastMessageTime设置为当前时间
//                if (empty($connection->lastMessageTime)) {
//                    $connection->lastMessageTime = $time_now;
//                    continue;
//                }
//                // 上次通讯时间间隔大于心跳间隔，则认为客户端已经下线，关闭连接
//                if ($time_now - $connection->lastMessageTime > HEARTBEAT_TIME) {
//                    $this->onClose($connection);
//                }
//            }
//        });
    }

    // 校验Token
    public function checkToken($connection, $token)
    {
        if (empty($token)) {
            $this->onError($connection, Status::NO_TOKEN, '请先登录');
            $connection->close();
        }
        $user = Jwt::verifyToken($token);
        if (!$user) {
            return false;
        }
        $user_id = $user['uid'];
        $key = sprintf(CacheKey::USER_TOKEN, $user_id);
        $new_token = redis()->get($key);
        if ($token != $new_token) {
            $this->onError($connection, Status::TOKEN_ERR, '登录验证失败');
            $connection->close();
        }
        // 判断连接是否占用
//        $redis = Redis(5);
//        $con_key = sprintf(CacheKey::CONNECT, $token);
//        if ($redis->get($con_key)) {
//            $this->onError($connection, Status::REPEAT_CONNECT, '连接已占用');
//            $connection->close();
//        } else {
//            $bind_key = sprintf(CacheKey::CLIENT_ID_UID, $connection->id);
//            $redis->set($bind_key, $new_token);
//            $redis->set($con_key, 1, 86400);
//            $this->user = $user;
//            $this->token = $token;
//        }
    }


//    public function checkToken($connection, $token)
//    {
//        if (empty($token)) {
//            $this->onError($connection, Status::NO_TOKEN, '请先登录');
//            $connection->close();
//        }
//        $vars = Cache::get($token);
//        if (!$vars) {
//            $this->onError($connection, Status::LOGIN_EXPIRE, '登录已过期');
//            $connection->close();
//        }
//        //查询用户数据
//        $user_data = Member::getInstance()->getOne(array('id' => $vars));
//        if (!$user_data) {
//            $this->onError($connection, Status::NO_USER, '用户不存在');
//            $connection->close();
//        }
//        // 通过用户id获取的token
//        $token_one = Cache::get($user_data['id']);
//        if ($token != $token_one) {
//            $this->onError($connection, Status::TOKEN_ERR, '登录验证失败');
//            $connection->close();
//        }
//        // 判断连接是否占用
//        $redis = Redis(5);
//        $con_key = sprintf(CacheKey::CONNECT, $token);
//        if ($redis->get($con_key)) {
//            $this->onError($connection, Status::REPEAT_CONNECT, '连接已占用');
//            $connection->close();
//        } else {
//            $bind_key = sprintf(CacheKey::CLIENT_ID_UID, $connection->id);
//            $redis->set($bind_key, $vars);
//            $redis->set($con_key, 1, 86400);
//            $this->user = $user_data;
//            $this->token = $token;
//        }
//    }

    /**
     * @Title: market
     * @Describe 数据源
     * @param $connection
     * @author lijunwei
     * @Date 2021/11/9 15:09
     */
    public function market($connection)
    {
        $redis = Redis(5);
        $list = [
            'type' => 'market',
            'code' => Status::SUCCESS,
            'data' => [],
            'msg' => '',
        ];
        $values = $redis->mget(["gc_market", "si_market", "cl_market", "hg_market"]);
        $info = [];
        foreach($values as $item) {
            $info[] = json_decode($item, true);
        }
        $list['data'] = $info;
        $msg = $this->send_msg($list);
        $connection->send($msg);
    }

    public function send_msg($data)
    {
//        $aes = config('aes');
//        $aes = config('app.aes');
//        $encrypted = openssl_encrypt(json_encode($data), 'aes-256-cbc', $aes['key'], OPENSSL_RAW_DATA, $aes['iv']);
//        return base64_encode($encrypted);
        return json_encode($data);
    }
}